package io.shallwe._admin.account;

import java.util.Date;
import java.util.List;

import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.tx.Tx;

import io.shallwe.common.model.Account;
import io.shallwe.common.model.Role;
import io.shallwe.common.model.Session;
import io.shallwe.login.LoginService;
import org.apache.commons.lang3.StringUtils;

public class AdminAccountService {
	@Inject
	LoginService loginSrv;
	
	private Account dao = new Account().dao();

	public Page<Account> paginate(int pageNum) {
		return dao.paginate(pageNum, 10, "select *", "from account order by id desc");
	}
	
	public Ret paginate(Integer offset,Integer pageSize,String userName,String realName) {
		Integer pageNumber=offset/pageSize+1;
		Kv queryParams=Kv.by("userName", userName).set("realName", realName);
		SqlPara sqlPara=dao.getSqlPara("account.paginate", queryParams);
		Page<Record> paginate = Db.paginate(pageNumber, pageSize, sqlPara);
		Ret ret = Ret.by("total", paginate.getTotalRow()).set("rows", paginate.getList());
		return ret;
	}

	public Account findById(String accountId) {
		return dao.findById(accountId);
	}
	
	public Account findByEmployeeNo(String employeeNo) {
		String sql="select * from account where employee_no = ?";
		return dao.findFirst(sql, employeeNo);
	}

	public Ret update(Account account) {

		if (isUserNameExists(account.getUserName(),account.getId())) {
			return Ret.fail("msg", "账号已经存在，请输入别的账号");
		}
		
		if (isEmployeeNumberExists(account.getEmployeeNo(),account.getId())) {
			return Ret.fail("msg", "账号已经存在，请输入别的账号");
		}
		account.keep("id","userName");
		account.update();
		return Ret.ok("msg", "账户更新成功");
	}

	/**
	 * 锁定账号
	 */
	public Ret lock(String loginAccountId, String lockedAccountId) {
		if (StrKit.equals(loginAccountId ,lockedAccountId)) {
			return Ret.fail("msg", "不能锁定自己的账号");
		}

		int n = Db.update("update account set status = ? where id=?", Account.STATUS_LOCK_ID, lockedAccountId);

		// 锁定后，强制退出登录，避免继续搞破坏
		List<Session> sessionList = Session.dao.find("select * from session where account_id = ?", lockedAccountId);
		if (sessionList != null) {
			for (Session session : sessionList) {			// 处理多客户端同时登录后的多 session 记录
				loginSrv.logout(session.getId());    // 清除登录 cache，强制退出
			}
		}

		if (n > 0) {
			return Ret.ok("msg", "锁定成功");
		} else {
			return Ret.fail("msg", "锁定失败");
		}
	}

	/**
	 * 解锁账号
	 */
	public Ret unlock(String accountId) {
		// 如果账户未激活，则不能被解锁
		int n = Db.update("update account set status = ? where id = ?", Account.STATUS_OK ,  accountId);
		Db.update("delete from session where account_id = ?", accountId);
		if (n > 0) {
			return Ret.ok("msg", "解锁成功");
		} else {
			return Ret.fail("msg", "解锁失败，可能是账户未激活，请查看账户详情");
		}
	}

	/**
	 * 添加角色
	 */
	public Ret addRole(String accountId, String roleId) {
		Record accountRole = new Record().set("accountId", accountId).set("roleId", roleId);
		Db.save("account_role", accountRole);
		return Ret.ok("msg", "添加角色成功");
	}

	/**
	 * 删除角色
	 */
	public Ret deleteRole(String accountId, String roleId) {
		Db.delete("delete from account_role where account_id=? and role_id=?", accountId, roleId);
		return Ret.ok("msg", "删除角色成功");
	}

	/**
	 * 标记出 account 拥有的角色
	 * 未来用 role left join account_role 来优化
	 */
	public void markAssignedRoles(Account account, List<Role> roleList) {
		String sql = "select top 1 account_id from account_role where account_id=? and role_id=? ";
		for (Role role : roleList) {
			String accountId = Db.queryStr(sql, account.getId(), role.getId());
			if (accountId != null) {
				// 设置 assigned 用于界面输出 checked
				role.put("assigned", true);
			}
		}
	}

	/**
	 * 获取 "后台账户/管理员" 列表，在 account_role 表中存在的账户(被分配过角色的账户)
	 * 被定义为 "后台账户/管理员"
	 *
	 * 该功能便于查看后台都有哪些账户被分配了角色，在对账户误操作分配了角色时，也便于取消角色分配
	 */
	public List<Record> getAdminList() {
		String sql = "select a.real_name, a.user_name, ar.*, r.name from account a, account_role ar, role r " +
				"where a.id = ar.account_id and ar.role_id = r.id " +
				"order by role_id asc";

		return Db.find(sql);
	}

	public Ret save(Account account) {
		if (isUserNameExists(account.getUserName(),"-1")) {
			return Ret.fail("msg", "账号已经存在，请输入别的账号");
		}
		
		if (isEmployeeNumberExists(account.getEmployeeNo(),"-1")) {
			return Ret.fail("msg", "账号已经存在，请输入别的账号");
		}
		
		account.setId(StrKit.getRandomUUID());
		String salt = HashKit.generateSaltForSha256();
		String password=account.getPassword();
		password = HashKit.sha256(salt + password);
		account.setPassword(password);
		account.setSalt(salt);
		account.setStatus(Account.STATUS_OK);
		account.setCreateAt(new Date());
		account.save();
		return Ret.ok("msg", "创建成功");
	}
	
	/**
	 * 账号是否重复
	 * @param userName
	 * @param id
	 * @return
	 */
	public  boolean isUserNameExists(String userName,String id) {
		userName = userName.toLowerCase().trim();
		Kv cond=Kv.by("userName", userName)
				.set("id", id);
		return Db.template("account.isUserNameExists",cond).queryStr()!=null;
	}
	/**
	 * 工号是否重复
	 * @param employeeNumber
	 * @param id
	 * @return
	 */
	public  boolean isEmployeeNumberExists(String employeeNumber,String id) {
		employeeNumber = employeeNumber.toLowerCase().trim();
		Kv cond=Kv.by("employeeNumber", employeeNumber)
				.set("id", id);
		return Db.template("account.isEmployeeNumberExists",cond).queryStr()!=null;
	}

	@Before(Tx.class)
	public Ret deleteAccount(String id) {
		dao.deleteById(id);
		Db.update("delete account_role from where accountId =?",id);
		return Ret.ok("msg","删除成功");
	}

	/**
	 * 隐藏个人中心中返回给前台的密码，只返回需要的字段
	 * @param account
	 * @return
	 */
	public Account hidePassword(Account account){
		Account a=new Account();
		a.setId(account.getId());
		a.setEmployeeNo(account.getEmployeeNo());
		a.setRealName(account.getRealName());
		a.setUserName(account.getUserName());
		return a;
	}

	/**
	 * 修改个人中心，当前只修改密码
	 * @param account
	 * @param password
	 * @param rePassword
	 * @return
	 */
	public Ret updatePersonalCenter(Account account,String password,String rePassword){
		if(!StringUtils.equals(password,rePassword)){
			return Ret.fail("msg","两次输入密码不一致，请重新输入");
		}
		String newPassword=HashKit.sha256(account.getSalt() + password);
		account.setPassword(newPassword);
		account.update();
		return Ret.ok("msg","修改成功");
	}
	
 
}
